package org.layui.dao.impl;

import org.layui.dao.UserDao;
import org.layui.entity.User;
import org.layui.utils.DBUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class UserDaoImpl implements UserDao {
    @Override
    public User selectUser(String username) {
        User user = null ;
        //第一：定义操作数据库的SQL语句
        String sql = "SELECT ID,USERNAME,PASSWORD,NAME,LEVEL,IMAGE,SEX,PHONE,ADDRESS,ZIPCODE,EMAIL,REGISTER_TIME,STATUS FROM USERS WHERE USERNAME=?" ;

        //第二：获取连接对象
        Connection conn = DBUtil.getConnection();

        //第三：使用连接对象，获取语句对象(PreparedStatement)，并预编译SQL语句
        PreparedStatement pstmt = null ;
        ResultSet rst = null ;
        try {
            pstmt= conn.prepareStatement(sql);

            //第四：设置数据
            //语法：语句对象.setXxx(问号占位符索引,数据) ;
            pstmt.setString(1,username);

            //第五：执行SQL语句，并接收返回结果
            //语句对象.executeUpdate() -> 增,删,改	   ->  返回的是受影响的记录数
            //语句对象.executeQuery()  -> 查			-> 	返回的是结果集(ResultSet)
            rst = pstmt.executeQuery() ;
            //第六：对结果进行处理
            //遍历结构集各行各列的数据，封装到相关的实体对象或集合
            //判断有没有数据:结果集对象.next()
            //获取结果集的数据:
            //结果集对象.getXxx(查询数据的索引) ;
            //结果集对象.getXxx(查询数据的字段名称) ;

            if(rst.next()) {
                // 1.读取数据
                int id = rst.getInt(1) ;
                String password = rst.getString(3) ;
                String name = rst.getString(4) ;
                String level = rst.getString(5) ;
                String image = rst.getString(6) ;
                String sex = rst.getString(7) ;
                String phone = rst.getString(8) ;
                String address = rst.getString(9) ;
                String zipCode = rst.getString(10) ;
                String email = rst.getString(11) ;
                Date regTime = rst.getTimestamp(12) ;
                int status = rst.getInt(13) ;

                // 2.创建实体对象
                user = new User() ;

                //3.封装数据
                user.setId(id);
                user.setUsername(username);
                user.setPassword(password);
                user.setName(name);
                user.setLevel(level);
                user.setImage(image);
                user.setSex(sex);
                user.setPhone(phone);
                user.setAddress(address);
                user.setZipCode(zipCode);
                user.setEmail(email);
                user.setRegisterTime(regTime);
                user.setStatus(status);

            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 第七：关闭对象
            DBUtil.close(conn,pstmt,rst);
        }

        return user;
    }

    @Override
    public List<User> queryUser(User user) {
        return null;
    }

    @Override
    public Long queryUserByPageCount(User user) {
        Long count = 0L;

        // 第一：定义操作数据库的SQL语句，动态添加条件
        StringBuilder sql =new StringBuilder("select count(id) from users where 1=1");

        // 1.定义集合，用于存储SQL语句的参数值
        List<Object> params = new ArrayList<Object>();

        // 2.拼接SQL语句
        if(user!=null && user.getUsername()!=null && !"".equals(user.getUsername().trim())) {
            sql.append(" and username like ?") ;
            params.add("%" + user.getUsername() + "%") ;
        }

        if(user!=null && user.getLevel()!=null && !"".equals(user.getLevel().trim())) {
            sql.append(" and level = ?") ;
            params.add(user.getLevel()) ;
        }

        // if(user!=null && user.getPhone()!=null) {
        //     sql.append(" and phone = ?") ;
        //     params.add(user.getPhone()) ;
        // }

        //第二：获取连接对象
        Connection conn = DBUtil.getConnection();

        //第三：使用连接对象，获取语句对象(PreparedStatement)，并预编译SQL语句
        PreparedStatement pstmt = null ;
        ResultSet rst = null ;
        try {
            pstmt= conn.prepareStatement(sql.toString());

            //第四：设置数据
            //语法：语句对象.setXxx(问号占位符索引,数据) ;
            //遍历集合，填充参数值
            for(int i=0;i<params.size();i++) {
                pstmt.setObject(i+1,params.get(i));
            }

            //第五：执行SQL语句，并接收返回结果
            //语句对象.executeUpdate() -> 增,删,改	   ->  返回的是受影响的记录数
            //语句对象.executeQuery()  -> 查			-> 	返回的是结果集(ResultSet)
            rst = pstmt.executeQuery() ;
            //第六：对结果进行处理
            //遍历结构集各行各列的数据，封装到相关的实体对象或集合
            //判断有没有数据:结果集对象.next()
            //获取结果集的数据:
            //结果集对象.getXxx(查询数据的索引) ;
            //结果集对象.getXxx(查询数据的字段名称) ;

            if(rst.next()) {
                count = rst.getLong(1) ;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 第七：关闭对象
            DBUtil.close(conn,pstmt,rst);
        }
        return count;
    }

    @Override
    public List<User> queryUserByPage(User user, Integer page, Integer limit) {
        List<User> list = new ArrayList<User>() ;

        // 第一：定义操作数据库的SQL语句，动态添加条件
        StringBuilder sql =new StringBuilder("select id,username,password,name,level,image,sex,phone,address,zipcode,email,register_time,status,rownumber from ( ");
        sql.append("select id,username,password,name,level,image,sex,phone,address,zipcode,email,register_time,status, row_number() over(order by u.id asc) as rownumber from users as u where 1=1") ;

        // 1.定义集合，用于存储SQL语句的参数值
        List<Object> params = new ArrayList<Object>();

        // 2.拼接SQL语句
        if(user!=null && user.getUsername()!=null && !"".equals(user.getUsername())) {
            sql.append(" and username like ?") ;
            params.add("%" + user.getUsername() + "%") ;
        }

        if(user!=null && user.getLevel()!=null && !"".equals(user.getLevel())) {
            sql.append(" and level = ?") ;
            params.add(user.getLevel()) ;
        }

        // if(user!=null && user.getPhone()!=null) {
        //     sql.append(" and phone = ?") ;
        //     params.add(user.getPhone()) ;
        // }

        sql.append(") as t") ;

        // 分页条件：(当前页数-1) * 每页记录数+1 and 当前页数 * 每页记录数
        sql.append(" where rownumber between ? and ?") ;
        params.add((page-1)*limit+1) ;
        params.add(page*limit) ;

        //第二：获取连接对象
        Connection conn = DBUtil.getConnection();

        //第三：使用连接对象，获取语句对象(PreparedStatement)，并预编译SQL语句
        PreparedStatement pstmt = null ;
        ResultSet rst = null ;
        try {
            pstmt= conn.prepareStatement(sql.toString());

            //第四：设置数据
            //语法：语句对象.setXxx(问号占位符索引,数据) ;
            //遍历集合，填充参数值
            for(int i=0;i<params.size();i++) {
                pstmt.setObject(i+1,params.get(i));
            }

            //第五：执行SQL语句，并接收返回结果
            //语句对象.executeUpdate() -> 增,删,改	   ->  返回的是受影响的记录数
            //语句对象.executeQuery()  -> 查			-> 	返回的是结果集(ResultSet)
            rst = pstmt.executeQuery() ;
            //第六：对结果进行处理
            //遍历结构集各行各列的数据，封装到相关的实体对象或集合
            //判断有没有数据:结果集对象.next()
            //获取结果集的数据:
            //结果集对象.getXxx(查询数据的索引) ;
            //结果集对象.getXxx(查询数据的字段名称) ;

            while(rst.next()) {
                // 1.读取数据
                int id = rst.getInt(1) ;
                String username = rst.getString(2) ;
                String password = rst.getString(3) ;
                String name = rst.getString(4) ;
                String level = rst.getString(5) ;
                String image = rst.getString(6) ;
                String sex = rst.getString(7) ;
                String phone = rst.getString(8) ;
                String address = rst.getString(9) ;
                String zipCode = rst.getString(10) ;
                String email = rst.getString(11) ;
                Date regTime = rst.getTimestamp(12) ;
                int status = rst.getInt(13) ;

                // 2.创建实体对象
                User u = new User() ;

                //3.封装数据
                u.setId(id);
                u.setUsername(username);
                u.setPassword(password);
                u.setName(name);
                u.setLevel(level);
                u.setImage(image);
                u.setSex(sex);
                u.setPhone(phone);
                u.setAddress(address);
                u.setZipCode(zipCode);
                u.setEmail(email);
                u.setRegisterTime(regTime);
                u.setStatus(status);

                list.add(u) ;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 第七：关闭对象
            DBUtil.close(conn,pstmt,rst);
        }
        return list;
    }

    @Override
    public int delete(int id) {
       int r = 0 ;

        // 第一：定义操作数据库的SQL语句，动态添加条件
        String sql = "delete from users where id=?" ;


        //第二：获取连接对象
        Connection conn = DBUtil.getConnection();

        //第三：使用连接对象，获取语句对象(PreparedStatement)，并预编译SQL语句
        PreparedStatement pstmt = null ;
        try {
            pstmt= conn.prepareStatement(sql.toString());

            //第四：设置数据
            pstmt.setInt(1,id);


            //第五：执行SQL语句，并接收返回结果
            //语句对象.executeUpdate() -> 增,删,改	   ->  返回的是受影响的记录数
            //语句对象.executeQuery()  -> 查			-> 	返回的是结果集(ResultSet)
            r = pstmt.executeUpdate();
            //第六：对结果进行处理
            //遍历结构集各行各列的数据，封装到相关的实体对象或集合
            //判断有没有数据:结果集对象.next()
            //获取结果集的数据:
            //结果集对象.getXxx(查询数据的索引) ;
            //结果集对象.getXxx(查询数据的字段名称) ;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 第七：关闭对象
            DBUtil.close(conn,pstmt,null);
        }
        return r;
    }

    @Override
    public int update(User user) {
        int r = 0 ;
        //第一：定义操作数据库的SQL语句
        String sql = "update users set sex=?,phone=?,address=?,zipCode=?,level=? where id=?" ;

        //第二：获取连接对象
        Connection conn = DBUtil.getConnection();

        //第三：使用连接对象，获取语句对象(PreparedStatement)，并预编译SQL语句
        PreparedStatement pstmt = null ;
        try {
            pstmt= conn.prepareStatement(sql);

            //第四：设置数据
            //语法：语句对象.setXxx(问号占位符索引,数据) ;

            pstmt.setString(1,user.getSex());
            pstmt.setString(2,user.getPhone());
            pstmt.setString(3,user.getAddress());
            pstmt.setString(4,user.getZipCode());
            pstmt.setString(5,user.getLevel());
            pstmt.setInt(6,user.getId());

            //第五：执行SQL语句，并接收返回结果
            //语句对象.executeUpdate() -> 增,删,改	   ->  返回的是受影响的记录数
            //语句对象.executeQuery()  -> 查			-> 	返回的是结果集(ResultSet)
            r = pstmt.executeUpdate() ;
            //第六：对结果进行处理
            //遍历结构集各行各列的数据，封装到相关的实体对象或集合
            //判断有没有数据:结果集对象.next()
            //获取结果集的数据:
            //结果集对象.getXxx(查询数据的索引) ;
            //结果集对象.getXxx(查询数据的字段名称) ;

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 第七：关闭对象
            DBUtil.close(conn,pstmt,null);
        }
        // 返回受影响行数
        return r;
    }

    @Override
    public int insert(User user) {
        int r = 0 ;
        //第一：定义操作数据库的SQL语句
        String sql = "insert into users(username,password,level,phone,status) values (?,?,?,?,?)" ;

        //第二：获取连接对象
        Connection conn = DBUtil.getConnection();

        //第三：使用连接对象，获取语句对象(PreparedStatement)，并预编译SQL语句
        PreparedStatement pstmt = null ;
        try {
            pstmt= conn.prepareStatement(sql);

            //第四：设置数据
            //语法：语句对象.setXxx(问号占位符索引,数据) ;

            pstmt.setString(1,user.getUsername());
            pstmt.setString(2,user.getPassword());
            pstmt.setString(3,"管理员");
            pstmt.setString(4,user.getPhone());
            pstmt.setInt(5,1);


            //第五：执行SQL语句，并接收返回结果
            //语句对象.executeUpdate() -> 增,删,改	   ->  返回的是受影响的记录数
            //语句对象.executeQuery()  -> 查			-> 	返回的是结果集(ResultSet)
            r = pstmt.executeUpdate() ;
            //第六：对结果进行处理
            //遍历结构集各行各列的数据，封装到相关的实体对象或集合
            //判断有没有数据:结果集对象.next()
            //获取结果集的数据:
            //结果集对象.getXxx(查询数据的索引) ;
            //结果集对象.getXxx(查询数据的字段名称) ;

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 第七：关闭对象
            DBUtil.close(conn,pstmt,null);
        }
        // 返回受影响行数
        return r;
    }
    @Override
    public int updateHead(String username, String head) {
        int r = 0 ;
        //第一：定义操作数据库的SQL语句
        String sql = "update users set image=? where username=?" ;

        //第二：获取连接对象
        Connection conn = DBUtil.getConnection();

        //第三：使用连接对象，获取语句对象(PreparedStatement)，并预编译SQL语句
        PreparedStatement pstmt = null ;
        try {
            pstmt= conn.prepareStatement(sql);

            //第四：设置数据
            //语法：语句对象.setXxx(问号占位符索引,数据) ;

            pstmt.setString(1,head);
            pstmt.setString(2,username);


            //第五：执行SQL语句，并接收返回结果
            //语句对象.executeUpdate() -> 增,删,改	   ->  返回的是受影响的记录数
            //语句对象.executeQuery()  -> 查			-> 	返回的是结果集(ResultSet)
            r = pstmt.executeUpdate() ;
            //第六：对结果进行处理
            //遍历结构集各行各列的数据，封装到相关的实体对象或集合
            //判断有没有数据:结果集对象.next()
            //获取结果集的数据:
            //结果集对象.getXxx(查询数据的索引) ;
            //结果集对象.getXxx(查询数据的字段名称) ;

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 第七：关闭对象
            DBUtil.close(conn,pstmt,null);
        }
        // 返回受影响行数
        return r;
    }

    @Override
    public int updatePwd(String username, String pass) {
        int r = 0 ;
        //第一：定义操作数据库的SQL语句
        String sql = "update users set password=? where username=?" ;

        //第二：获取连接对象
        Connection conn = DBUtil.getConnection();

        //第三：使用连接对象，获取语句对象(PreparedStatement)，并预编译SQL语句
        PreparedStatement pstmt = null ;
        try {
            pstmt= conn.prepareStatement(sql);

            //第四：设置数据
            //语法：语句对象.setXxx(问号占位符索引,数据) ;
            pstmt.setString(1,pass);
            pstmt.setString(2,username);

            //第五：执行SQL语句，并接收返回结果
            //语句对象.executeUpdate() -> 增,删,改	   ->  返回的是受影响的记录数
            //语句对象.executeQuery()  -> 查			-> 	返回的是结果集(ResultSet)
            r = pstmt.executeUpdate() ;
            //第六：对结果进行处理
            //遍历结构集各行各列的数据，封装到相关的实体对象或集合
            //判断有没有数据:结果集对象.next()
            //获取结果集的数据:
            //结果集对象.getXxx(查询数据的索引) ;
            //结果集对象.getXxx(查询数据的字段名称) ;

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 第七：关闭对象
            DBUtil.close(conn,pstmt,null);
        }
        // 返回受影响行数
        return r;
    }
}
